package com.systar.activity.report;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import com.systar.activity.report.actions.ActionType;

/**
 * Helper class to handle requests
 */
class RequestHelper
{
	private RequestHelper()
	{
		// cannot instantiate
	}

	/**
	 * Returns a map of the parameter names/value contained in this request.
	 * 
	 * @param request
	 *            the http request
	 * @return the map of the parameters
	 */
	static Map<RequestParameter,String> getRequestParameters(HttpServletRequest request)
	{
		Map<RequestParameter,String> mapParams = new HashMap<RequestParameter,String>();
		@SuppressWarnings("rawtypes")
		Enumeration parameterNames = request.getParameterNames();
		while (parameterNames.hasMoreElements())
		{
			String paramName = (String) parameterNames.nextElement();
			String paramValue = request.getParameter(paramName);
			RequestParameter param = RequestParameter.fromString(paramName);
			if (param != null)
				mapParams.put(param, paramValue);
		}
		return mapParams;
	}

	/**
	 * Returns a map of the parameter names/value contained in this request.
	 * 
	 * @param parameters the Servlet parameters
	 * @return the type of action, or null if not declared
	 */
	static ActionType getAction(Map<RequestParameter, String> parameters)
	{
		if (parameters==null || !parameters.containsKey(RequestParameter.action))
			return null;
		
		String actionName = parameters.get(RequestParameter.action);
		return ActionType.fromString(actionName);
	}

	/**
	 * Search for possible script or SQL injection
	 * 
	 * @param parameters the Servlet parameters
	 * @return true if no injection, false 
	 */
	static boolean detectInjections(Map<RequestParameter, String> parameters) 
	{
		for (RequestParameter param : parameters.keySet())
		{
			String paramValue = parameters.get(param);
			boolean detect = param.isSqlParameter() ? 
					detectSqlInjection(paramValue) : detectScriptInjection(paramValue);
			if (detect)
				return true;
		}
		return false;
	}

	/**
	 * Check string for script injection. 
	 * Catch javascript:, <xxx script xxx>, eval(xxx)
	 * 
	 * @param paramValue the string to check
	 * @return true if a script was detected
	 */
	static boolean detectScriptInjection(String paramValue)
	{
		if (paramValue == null)
			return false;

		String patternJavascript = "[\\\"\\\'][\\s]*javascript[\\s]*:(.*)[\\\"\\\']";
		if (Pattern.compile(patternJavascript).matcher(paramValue).find())
			return true;

		String patternScript = "<.*script.*script.*>|<.*script.*>";
		if (Pattern.compile(patternScript).matcher(paramValue).find())
			return true;

		String patternEval = "eval(\\s)*\\(.*\\)";
		if (Pattern.compile(patternEval).matcher(paramValue).find())
			return true;

		return false;
	}

	/**
	 * Check string for sql injection. 
	 * Catch select..from, update..set, delete..from, insert into
	 * 
	 * @param paramValue the string to check
	 * @return true if a script was detected
	 */
	static boolean detectSqlInjection(String paramValue)
	{
		if (paramValue == null)
			return false;
		paramValue = paramValue.toLowerCase();

		String patternSelect = "select[\\s]+.*from[\\s]+";
		if (Pattern.compile(patternSelect).matcher(paramValue).find())
			return true;

		String patternInsert = "insert[\\s]+into[\\s]+";
		if (Pattern.compile(patternInsert).matcher(paramValue).find())
			return true;

		String patternDelete = "delete[\\s]+.*from[\\s]+";
		if (Pattern.compile(patternDelete).matcher(paramValue).find())
			return true;

		String patternUpdate = "update[\\s]+.*set[\\s]+";
		if (Pattern.compile(patternUpdate).matcher(paramValue).find())
			return true;

		return false;
	}

}
